package com.paas.form.handler;

import com.alibaba.fastjson.JSONObject;
import com.paas.common.auth.service.IPermissionService;
import com.paas.common.jdbc.JdbcSql;
import com.paas.common.jdbc.model.DbConfig;
import com.paas.common.model.DataBaseEntity;
import com.paas.common.util.AppUtil;
import com.paas.common.util.BeanUtil;
import com.paas.form.entity.*;
import com.paas.form.enums.RunStateEnums;
import com.paas.form.handler.util.FormJobHandlerUtil;
import com.paas.form.service.*;
import com.paas.form.vo.FormJobTaskModelVo;
import com.paas.plus.tool.form.model.View;
import com.paas.plus.tool.form.server.FormService;
import com.paas.plus.tool.realTimeDistributed.model.RealTimeDistributeConfig;
import com.paas.plus.tool.realTimeDistributed.server.IRealTimeDistributeServer;
import com.paas.scheduler.exception.SchedulerException;
import com.paas.scheduler.model.JobInstance;
import com.paas.scheduler.spi.JobHandler;
import com.paas.tool.feign.service.IMdmToolsRealtimeDistributionService;
import com.publics.feign.service.IUcDataBaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;

import java.util.*;

@Slf4j
public class OffLineJobHandler implements JobHandler {

    private IRealTimeDistributeServer realTimeDistributeServer;
    private IMdmToolsRealtimeDistributionService realtimeDistributionService;
    private IFormTaskService formTaskService;
    private IFormModelService modelService;
    private IFormModelParamsService formModelParamsService;
    private IFormTaskParamsService formTaskParamsService;
    private IUcDataBaseService dataBaseService;
    private IFormTaskMapperService formTaskMapperService;
    private FormService formService;
    private IFormTaskLogService formTaskLogService;

    private FormTaskLogEntity formTaskLogEntity;
    private FormJobTaskHandler formJobTaskHandler;

    private FormJobTaskModelVo formJobTaskModelVo;

    private Environment environment;

    private String appCode;

    private String publicsKey;

    private String getThirdPartyToken(String appCode, String publicsKey) {
        IPermissionService permissionService = (IPermissionService) AppUtil.getBean(IPermissionService.class);
        log.info("mdm开始获取token");
        // 调用第三方应用获取令牌接口
        String token = permissionService.createThirdAppToken(appCode, publicsKey);
        log.info("mdm获取token成功：{}", token);
        return token;
    }

    @Override
    public String getType() {
        return "MDM_TASK";
    }

    @Override
    public void init(JobInstance jobInstance) {
        log.info("开始初始化参数");
        initService();
        initParams(jobInstance);
    }

    @Override
    public void start() {
        log.info("任务执行开始");
        DataBaseEntity db = formJobTaskModelVo.getDb();
        DbConfig config = new DbConfig(db.getJdbcDrivers(), db.getJdbcUrl(), db.getJdbcUser(), db.getJdbcPassword(), db.getDbName());
        JdbcSql jdbcSql = new JdbcSql(config);
        int failedCount = 0;
        Boolean flag = true;
        long startTime = System.currentTimeMillis();
        try {
            formTaskLogEntity.setStartTime(new Date());
            formTaskLogService.saveOrUpdate(formTaskLogEntity);
            jdbcSql.executeStreamQuery(formJobTaskModelVo.getExecuteSql(), formJobTaskHandler);
            if (formJobTaskHandler.getIncrementalDistributionList().size() > 0) {
                com.alibaba.fastjson2.JSONObject object = realTimeDistributeServer.executeIncrementalDistribution(formJobTaskHandler.getIncrementalDistributionList());
                int count = formJobTaskHandler.getFailedCount();
                failedCount = count + Integer.valueOf(object.get("failedCount").toString());
            }
        } catch (Exception e) {
            flag = false;
            formTaskLogEntity.setError(e.toString());
        } finally {
            if (!flag) {
                formTaskLogEntity.setStatus(RunStateEnums.error.getValue());
            } else {
                formTaskLogEntity.setStatus(RunStateEnums.finish.getValue());
            }
            formTaskLogEntity.setFailedRecords(failedCount);
            long endTime = System.currentTimeMillis();
            formTaskLogEntity.setEndTime(new Date());
            formTaskLogEntity.setTotalTime(String.valueOf((endTime - startTime)));
            formTaskLogEntity.setRecords(formJobTaskHandler.getCount());
            formTaskLogService.saveOrUpdate(formTaskLogEntity);
        }
    }

    @Override
    public void destroy() {

    }

    @Override
    public JobHandler clone() {
        try {
            return (JobHandler) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new SchedulerException("调度服务克隆异常！", e);
        }
    }


    /**
     * 初始化参数
     */
    private void initParams(JobInstance jobInstance) {
        Map<String, Object> resultMap;
        List<Map<String, Object>> sqlValueList = null;
        Map<String, String> columnMap = null;
        FormTaskEntity formTaskEntity = formTaskService.getById(jobInstance.getBusId());

        FormModelEntity formModelEntity = modelService.getById(formTaskEntity.getModelId());

        FormModelParamsEntity formModelParamsEntity = new FormModelParamsEntity();
        Map<String, FormModelParamsEntity> tempFormModelMap = new HashMap<>();
        //查询规则模型params
        formModelParamsEntity.setModelId(formModelEntity.getId());
        List<FormModelParamsEntity> list = formModelParamsService.getList(formModelParamsEntity);
        for (FormModelParamsEntity modelParamsEntity : list) {
            tempFormModelMap.put(modelParamsEntity.getId(), modelParamsEntity);
        }
        //查询任务参数
        FormTaskParamsEntity formTaskParamsEntity = new FormTaskParamsEntity();
        formTaskParamsEntity.setTaskId(formTaskEntity.getId());
        List<FormTaskParamsEntity> formTaskParamsList = formTaskParamsService.getList(formTaskParamsEntity);
        if (formTaskParamsList.size() > 0) {
            resultMap = FormJobHandlerUtil.parseParams(formTaskParamsList, tempFormModelMap);
            sqlValueList = (List<Map<String, Object>>) resultMap.get("params");
            columnMap = (Map<String, String>) resultMap.get("column");
        }

        if (BeanUtil.isEmpty(formJobTaskModelVo)) {
            formJobTaskModelVo = new FormJobTaskModelVo();
        }
        //获取对应字段,对应的字段属性
        if (BeanUtil.isNotEmpty(sqlValueList) && BeanUtil.isNotEmpty(columnMap)) {
            for (Map<String, Object> map : sqlValueList) {
                Iterator<Map.Entry<String, String>> iterator = columnMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, String> next = iterator.next();
                    if (map.containsKey(next.getKey())) {
                        map.put("tempType", next.getValue());
                        columnMap.remove(next.getKey());
                        break;
                    }
                }
            }
        }
        //获取yml文件中appCode、publicsKey
        appCode = environment.getProperty("paas.token.thirdParty.appCode");
        publicsKey = environment.getProperty("paas.token.thirdParty.publicsKey");
        String thirdPartyToken = getThirdPartyToken(appCode, publicsKey);
        formJobTaskModelVo.setDb(dataBaseService.asyncQueryById(formModelEntity.getDatabaseId(), thirdPartyToken));
        formJobTaskModelVo.setExecuteSql(FormJobHandlerUtil.formatSql(formModelEntity.getExcelSql(), sqlValueList));

        //获取分发配置
        RealTimeDistributeConfig distributionConfiguration = realtimeDistributionService.getDistributionConfiguration(formTaskEntity.getViewId(), "2", thirdPartyToken);
        FormTaskMapperEntity formTaskMapperEntity = new FormTaskMapperEntity();
        formTaskMapperEntity.setTaskId(formTaskEntity.getId());
        List<FormTaskMapperEntity> formTaskMapperList = formTaskMapperService.getList(formTaskMapperEntity);
        //初始化handler参数
        if (BeanUtil.isEmpty(formJobTaskHandler)) {
            formJobTaskHandler = new FormJobTaskHandler();
        }
        View view = formService.getViewById(formTaskEntity.getViewId());
        formJobTaskHandler.setView(view);
        formJobTaskHandler.setDb(dataBaseService.asyncQueryById(view.getDatasourceId(), thirdPartyToken));
        formJobTaskHandler.setColumnMapperMap(parseColumnMapperMap(formTaskMapperList));
        formJobTaskHandler.setRealTimeDistributeConfig(distributionConfiguration);
        formJobTaskHandler.setJobId(jobInstance.getInstId());
        if (BeanUtil.isEmpty(formTaskLogEntity)) {
            formTaskLogEntity = new FormTaskLogEntity();
        }
        formTaskLogEntity.setJobId(jobInstance.getInstId());
        formTaskLogEntity.setTaskId(jobInstance.getBusId());
        formTaskLogEntity.setParams(JSONObject.toJSONString(sqlValueList));
        formTaskLogEntity.setAppId(jobInstance.getAppId());
        formTaskLogEntity.setOrgId(jobInstance.getOrgId());
        formTaskLogEntity.setStatus(RunStateEnums.start.getValue());
        formTaskLogEntity.setApiConfNum(distributionConfiguration.getRealTimeDistributeInterfaceConfigList().size());
        formTaskLogEntity.setTabConfNum(distributionConfiguration.getRealTimeDistributeTableConfigList().size());
    }

    private Map<String, String> parseColumnMapperMap(List<FormTaskMapperEntity> formTaskMapperList) {
        Map<String, String> map = new HashMap<>();
        for (FormTaskMapperEntity formTaskMapperEntity : formTaskMapperList) {
            map.put(formTaskMapperEntity.getSourceCloumn(), formTaskMapperEntity.getTargetCloumn());
        }
        return map;
    }


    private void initService() {
        if (realtimeDistributionService == null) {
            realtimeDistributionService = (IMdmToolsRealtimeDistributionService) AppUtil.getBean(IMdmToolsRealtimeDistributionService.class);
        }
        if (formTaskService == null) {
            formTaskService = (IFormTaskService) AppUtil.getBean(IFormTaskService.class);
        }
        if (modelService == null) {
            modelService = (IFormModelService) AppUtil.getBean(IFormModelService.class);
        }
        if (formModelParamsService == null) {
            formModelParamsService = (IFormModelParamsService) AppUtil.getBean(IFormModelParamsService.class);
        }
        if (formTaskParamsService == null) {
            formTaskParamsService = (IFormTaskParamsService) AppUtil.getBean(IFormTaskParamsService.class);
        }
        if (dataBaseService == null) {
            dataBaseService = (IUcDataBaseService) AppUtil.getBean(IUcDataBaseService.class);
        }
        if (formTaskMapperService == null) {
            formTaskMapperService = (IFormTaskMapperService) AppUtil.getBean(IFormTaskMapperService.class);
        }
        if (formService == null) {
            formService = (FormService) AppUtil.getBean(FormService.class);
        }
        if (environment == null) {
            environment = (Environment) AppUtil.getBean(Environment.class);
        }
        if (formTaskLogService == null) {
            formTaskLogService = (IFormTaskLogService) AppUtil.getBean(IFormTaskLogService.class);
        }

        if (realTimeDistributeServer == null){
            realTimeDistributeServer = (IRealTimeDistributeServer) AppUtil.getBean(IRealTimeDistributeServer.class);
        }
    }
}
